﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using fjycHRTest;
using Wicresoft.fjyc.External.Interface;
using Wicresoft.fjyc.Integration.HR.Interface;
using System.DirectoryServices.Protocols;
using System.Reflection;

namespace Wicresoft.fjyc.Integration.Engine
{
    public class HREngine
    {
        private const int MAX_BATCH = 10;

        public void Execute()
        {
            /*get data from HR interface and update local db*/
            var dp = QueryDatePeroid();
            string beginTime = dp.Start.ToString();
            string endTime = dp.End.ToString();
            GetDepartmentFromHR(beginTime, endTime);
            GetEmployeeFromHR(beginTime, endTime);


            /*push to clients*/

            var clients = GetClients();

            DateTimePeroid dtp = new DateTimePeroid();
            dtp.End = DateTime.Now;

            bool NoError;
            DateTime start;
            IEnumerable<Employee> employees;

            foreach (var client in clients)
            {
                NoError = true;
                start = client.GetStartDate();
                dtp.Start = start;

                //qeury local db according to the dp
                employees = GetEmployeeFromLocalDB(start.ToString());

                foreach (var emp in employees)
                {
                    //push to client
                    try
                    {
                        client.PushEmployee(emp);
                    }
                    catch (Exception e)
                    {
                        NoError = false;
                    }
                }
                if (NoError)
                {
                    client.PushEndDate(dtp);
                }
                client.Dispose();
            }
        }

        public IEnumerable<IEmployeeOperation> GetClients()
        {
            IList<IEmployeeOperation> clients = new List<IEmployeeOperation>();
            string clientStr = ConfigurationManager.AppSettings["ClientsAsNameClName"];
            var clientStrs = clientStr.Split(';');
            foreach (var item in clientStrs)
            {
                var dllclass = item.Split(',');
                var dllPath = dllclass[0];
                var className = dllclass[1];
                var assembly = Assembly.Load(dllPath);
                var instance = (IEmployeeOperation)assembly.CreateInstance(dllPath + "." + className);
                clients.Add(instance);
            }
            return clients;
        }

        //根据同步开始时间和结束时间从HR库同步员工信息到本地库
        public void GetEmployeeFromHR(string beginTime, string endTime)
        {
            using (EASLoginProxyClient client = new EASLoginProxyClient())
            {
                var context = client.login("user", "kingdee", "eas", "eas", "l2", 1);

                using (WSPersonWebServiceFacadeSrvProxyClient person = new WSPersonWebServiceFacadeSrvProxyClient())
                {
                    int count = person.getPersonsCount(beginTime, endTime);
                    int tmp_start = 1;
                    int tmp_count = MAX_BATCH;

                    using (HREntities entity = new HREntities())
                    {
                        while (true)
                        {
                            if (tmp_start + tmp_count > count)
                            {
                                tmp_count = count - tmp_start + 1;
                                if (tmp_count < 1) break;
                            }
                            string[][] values = null;
                            try
                            {
                                values = person.getPersons(beginTime, endTime, tmp_start, tmp_count);
                                int inner_index = 0;
                                foreach (string[] s in values)
                                {
                                    var personCode = s[2].ToString();
                                    FJ_HR2 record = (from r in entity.FJ_HR2
                                                     where r.PERSONCODE == personCode
                                                     select r).First();

                                    if (record != null)
                                    {
                                        //string[] uidAndMail = GetLDAPUidAndMail(s[1], s[8], s[9]);
                                        record.PERSONID = s[0];
                                        record.CNAME = s[1];
                                        record.PERSONCODE = s[2];
                                        record.GENDER = Int32.Parse(s[3]);
                                        if (s[4] == null)
                                            record.BIRTH = null;
                                        else
                                            record.BIRTH = DateTime.Parse(s[4]);
                                        record.EMAIL = s[5];
                                        record.COMPANY = s[6];
                                        record.COMPANYCODE = s[7];
                                        record.DEPT = s[8];
                                        record.DEPTCODE = s[9];
                                        record.MANAGEWORK = s[10];
                                        record.SEQUENCEINDEPT = s[11];
                                        record.POSITIONTYPENAME = s[12];
                                        record.POSITIONTYPECODE = s[13];
                                        record.POSITIONNAME = s[14];
                                        record.POSITIONCODE = s[15];
                                        record.POLITICALFACENAME = s[16];
                                        record.POLITICALFACECODE = s[17];
                                        record.EMPLOYEEPROPNAME = s[18];
                                        record.EMPLOYEEPROPCODE = s[19];
                                        if (s[20] == null)
                                            record.JOBSTART = null;
                                        else
                                            record.JOBSTART = DateTime.Parse(s[20]);
                                        record.STATUS = s[21];
                                        record.STATUSCODE = s[22];
                                        record.DIPLOMANAME = s[23];
                                        record.DIPLOMACODE = s[24];
                                        record.DELETESTATUS = Int32.Parse(s[25]);
                                        record.UNKNOW1 = s[26];
                                        record.QUERYSTARTDATE = DateTime.Parse(beginTime);
                                        record.QUERYENDDATE = DateTime.Parse(endTime);

                                        entity.SaveChanges();
                                    }
                                    else
                                    {
                                        FJ_HR2 newHR = entity.CreateObject<FJ_HR2>();
                                        //string[] uidAndMail = GetLDAPUidAndMail(s[1], s[8], s[9]);
                                        newHR.PERSONID = s[0];
                                        newHR.CNAME = s[1];
                                        newHR.PERSONCODE = s[2];
                                        newHR.GENDER = Int32.Parse(s[3]);
                                        if (s[4] == null)
                                            newHR.BIRTH = null;
                                        else
                                            newHR.BIRTH = DateTime.Parse(s[4]);
                                        newHR.EMAIL = s[5];
                                        newHR.COMPANY = s[6];
                                        newHR.COMPANYCODE = s[7];
                                        newHR.DEPT = s[8];
                                        newHR.DEPTCODE = s[9];
                                        newHR.MANAGEWORK = s[10];
                                        newHR.SEQUENCEINDEPT = s[11];
                                        newHR.POSITIONTYPENAME = s[12];
                                        newHR.POSITIONTYPECODE = s[13];
                                        newHR.POSITIONNAME = s[14];
                                        newHR.POSITIONCODE = s[15];
                                        newHR.POLITICALFACENAME = s[16];
                                        newHR.POLITICALFACECODE = s[17];
                                        newHR.EMPLOYEEPROPNAME = s[18];
                                        newHR.EMPLOYEEPROPCODE = s[19];
                                        if (s[20] == null)
                                            newHR.JOBSTART = null;
                                        else
                                            newHR.JOBSTART = DateTime.Parse(s[20]);
                                        newHR.STATUS = s[21];
                                        newHR.STATUSCODE = s[22];
                                        newHR.DIPLOMANAME = s[23];
                                        newHR.DIPLOMACODE = s[24];
                                        newHR.DELETESTATUS = Int32.Parse(s[25]);
                                        newHR.UNKNOW1 = s[26];
                                        newHR.QUERYSTARTDATE = DateTime.Parse(beginTime);
                                        newHR.QUERYENDDATE = DateTime.Parse(endTime);


                                        //根据中文名获取拼音并保证不重复
                                        var uid = GetUid(s[1]);
                                        List<FJ_HR2> dupName = (from r in entity.FJ_HR2
                                                                where r.O_UID.Contains(uid)
                                                                select r).ToList();
                                        int existsCount = dupName.Count;
                                        if (existsCount == 0)
                                        {
                                            newHR.O_UID = uid;
                                        }
                                        else
                                        {
                                            newHR.O_UID = uid + dupName.Count;
                                        }

                                        newHR.O_INDEX = tmp_start + inner_index;

                                        entity.AddToFJ_HR2(newHR);
                                        entity.SaveChanges();
                                        inner_index++;
                                    }
                                }
                            }
                            catch (Exception ex) { }
                            tmp_start += tmp_count;
                        }
                    }
                }
            }
        }

        //拼接LADP查询条件
        public static string GetLDAPConditions(string deptCode)
        {
            using (HREntities entity = new HREntities())
            {
                FJ_ORG2 org = (from o in entity.FJ_ORG2
                               where o.ORGCODE == deptCode
                               select o).First();
                string condition = string.Empty;
                if (org != null)
                {
                    var parentOrgCode = org.PARENTORGCODE;
                    while (true)
                    {
                        var result = (from o in entity.FJ_ORG2
                                      where o.ORGCODE == parentOrgCode
                                      select o);

                        if (result.Count() > 0)
                        {
                            FJ_ORG2 orgs = result.First();
                            condition = condition + ",OU=" + orgs.ORGNAME;
                            parentOrgCode = orgs.PARENTORGCODE;
                        }
                        else
                        {
                            break;
                        }
                    }
                }
                return condition;
            }
        }

        //LDAP查询用户Uid和Email
        public string[] GetLDAPUidAndMail(string cName, string deptName, string deptCode)
        {
            using (LdapConnection ldap = new LdapConnection(new LdapDirectoryIdentifier("10.188.239.105"), null, AuthType.Anonymous))
            {
                ldap.SessionOptions.ProtocolVersion = 3;

                //var di = ldap.Directory;
                string condition = GetLDAPConditions(deptCode);
                string targetOu = string.Format("CN={0},OU={1}{2},O=福建烟草", cName, deptName, condition);

                // create a search filter to find all objects
                string ldapSearchFilter = "(objectClass=*)";
                string[] attribs = { "mail", "uid" };
                string[] result = new string[2] { string.Empty, string.Empty };
                try
                {
                    SearchRequest searchRequest = new SearchRequest
                                                    (targetOu,
                                                      ldapSearchFilter,
                                                      SearchScope.Subtree,
                                                      attribs);

                    // cast the returned directory response as a SearchResponse object
                    SearchResponse searchResponse =
                                (SearchResponse)ldap.SendRequest(searchRequest);

                    // enumerate the entries in the search response
                    foreach (SearchResultEntry entry in searchResponse.Entries)
                    {
                        SearchResultAttributeCollection attributes = entry.Attributes;

                        foreach (DirectoryAttribute attribute in attributes.Values)
                        {
                            for (int i = 0; i < attribute.Count; i++)
                            {
                                if (attribute[i] is string)
                                {
                                    if (attribute.Name == "mail")
                                    {
                                        result[0] = attribute[i].ToString();
                                    }
                                    else if (attribute.Name == "uid")
                                    {
                                        result[1] = attribute[i].ToString();
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception ex) { }
                return result;
            }
        }

        //根据同步开始时间和结束时间从HR库同步部门信息到本地库
        public void GetDepartmentFromHR(string beginTime, string endTime)
        {
            using (EASLoginProxyClient client = new EASLoginProxyClient())
            {
                var context = client.login("user", "kingdee", "eas", "eas", "l2", 1);

                using (WSPersonWebServiceFacadeSrvProxyClient person = new WSPersonWebServiceFacadeSrvProxyClient())
                {
                    int orgcount = person.getOrgUnitsCount(null, beginTime, endTime);
                    int tmp_start = 1;
                    int tmp_count = MAX_BATCH;

                    using (HREntities entity = new HREntities())
                    {
                        while (true)
                        {
                            if (tmp_start + tmp_count > orgcount)
                            {
                                tmp_count = orgcount - tmp_start + 1;
                                if (tmp_count < 1) break;
                            }
                            string[][] values = null;
                            try
                            {
                                values = person.getOrgUnits(null, beginTime, endTime, tmp_start, tmp_count);
                                int inner_index = 0;
                                foreach (string[] s in values)
                                {
                                    var orgCode = s[0].ToString();
                                    FJ_ORG2 org = (from o in entity.FJ_ORG2
                                                   where o.ORGCODE == orgCode
                                                   select o).First();
                                    if (org != null)
                                    {
                                        org.ORGCODE = s[0];
                                        org.ORGNAME = s[1];
                                        org.ORGNAME2 = s[2];
                                        org.USEDFLAG = Int32.Parse(s[3]);
                                        org.PARENTORGCODE = s[4];
                                        org.ORGTYPE = s[5];
                                        org.ORGPROTYPE = s[6];
                                        org.ORGLEVEL = s[7];
                                        org.ORGREGION = s[8];
                                        org.ORGFILENAME = s[9];
                                        org.QUERYSTARTDATE = DateTime.Parse(beginTime);
                                        org.QUERYENDDATE = DateTime.Parse(endTime);
                                        entity.SaveChanges();
                                    }

                                    else
                                    {
                                        org = new FJ_ORG2();
                                        org.ORGCODE = s[0];
                                        org.ORGNAME = s[1];
                                        org.ORGNAME2 = s[2];
                                        org.USEDFLAG = Int32.Parse(s[3]);
                                        org.PARENTORGCODE = s[4];
                                        org.ORGTYPE = s[5];
                                        org.ORGPROTYPE = s[6];
                                        org.ORGLEVEL = s[7];
                                        org.ORGREGION = s[8];
                                        org.ORGFILENAME = s[9];
                                        org.QUERYSTARTDATE = DateTime.Parse(beginTime);
                                        org.QUERYENDDATE = DateTime.Parse(endTime);
                                        org.O_INDEX = tmp_start + tmp_count;

                                        entity.AddToFJ_ORG2(org);
                                        entity.SaveChanges();
                                        inner_index++;
                                    }
                                }
                            }
                            catch (Exception ex) { }
                            tmp_start += tmp_count;
                        }
                    }
                }
            }
        }

        //获取上次同步时间
        public DateTimePeroid QueryDatePeroid()
        {
            using (HREntities entity = new HREntities())
            {
                FJ_HR2 record = (from r in entity.FJ_HR2
                                 orderby r.QUERYENDDATE descending
                                 select r).First();
                DateTimePeroid peroid = new DateTimePeroid();
                peroid.Start = record.QUERYENDDATE;
                peroid.End = DateTime.Now;
                return peroid;
            }
        }

        public List<Employee> GetEmployeeFromLocalDB(string lastEndTime)
        {
            List<Employee> employeeList = new List<Employee>();
            using (HREntities entity = new HREntities())
            {
                var queryEndData = DateTime.Parse(lastEndTime);
                List<FJ_HR2> recordList = (from r in entity.FJ_HR2
                                           where r.QUERYENDDATE >= queryEndData
                                           select r).ToList();
                foreach (var record in recordList)
                {
                    var employee = ConvertToEmployee(record);
                    if (!string.IsNullOrWhiteSpace(employee.O_UID)) employeeList.Add(employee);
                }

                return employeeList;
            }

        }

        public Employee ConvertToEmployee(FJ_HR2 record)
        {
            Employee employee = new Employee();
            employee.PERSONID = record.PERSONID;
            employee.CNAME = record.CNAME;
            employee.PERSONCODE = record.PERSONCODE;
            employee.GENDER = record.GENDER;
            employee.BIRTH = record.BIRTH;
            employee.EMAIL = record.EMAIL;
            employee.COMPANY = record.COMPANY.Substring(0, record.COMPANY.IndexOf('(') - 1);
            employee.DEPT = record.DEPT;
            employee.DEPTCODE = record.DEPTCODE;
            employee.MANAGEWORK = record.MANAGEWORK;
            employee.SEQUENCEINDEPT = record.SEQUENCEINDEPT;
            employee.POSITIONTYPENAME = record.POSITIONTYPENAME;
            employee.POSITIONTYPECODE = record.POSITIONTYPECODE;
            employee.POSITIONNAME = record.POSITIONNAME;
            employee.POSITIONCODE = record.POSITIONCODE;
            employee.POLITICALFACENAME = record.POLITICALFACENAME;
            employee.POLITICALFACECODE = record.POLITICALFACECODE;
            employee.EMPLOYEEPROPNAME = record.EMPLOYEEPROPNAME;
            employee.EMPLOYEEPROPCODE = record.EMPLOYEEPROPCODE;
            employee.JOBSTART = record.JOBSTART;
            employee.STATUS = record.STATUS;
            employee.STATUSCODE = record.STATUSCODE;
            employee.DIPLOMANAME = record.DIPLOMANAME;
            employee.DIPLOMACODE = record.DIPLOMACODE;
            employee.DELETESTATUS = record.DELETESTATUS;
            employee.UNKNOW1 = record.UNKNOW1;
            employee.O_UID = record.O_UID;

            return employee;
        }

        public string GetUid(string cname)
        {
            string quanpin = string.Empty;
            //生成全拼
            GetPinyin npy = new GetPinyin();
            quanpin = npy.convert(cname, false);
            return quanpin;
        }
    }
}

